package com.cvdnn.serial;

import android.Loople;
import android.annotation.SuppressLint;
import android.concurrent.RunState;
import android.log.Log;
import android.os.Bundle;
import android.serialport.api.SerialInode;
import android.text.Chars;
import android.util.Potency;

import androidx.appcompat.app.AppCompatActivity;

import com.cvdnn.serial.databinding.ActMainBinding;

import java.util.ArrayList;

import iot.proto.DefiningDomain.UnitIndex;
import iot.proto.DefiningDomain.ValueTypes;
import iot.proto.M2spLite;
import iot.proto.MultiMeaasgeInterface.UnitAttribute;
import iot.proto.MultiMeaasgeInterface.UnitMeta;
import iot.proto.serical.SerialPipeline;

import static iot.proto.M2spLite.ACT_QUERY;
import static iot.proto.M2spLite.ACT_REPORT;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

public class MainActivity extends AppCompatActivity {
    public static final String TAG = "MainActivity";

    public static final UnitAttribute TEMPERATURE = M2spLite.attr(UnitIndex.TEMPERATURE, ACT_REPORT | ACT_QUERY, ValueTypes.INT64);

    private final RunState mRunState = new RunState(false);

    private ActMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView((binding = ActMainBinding.inflate(getLayoutInflater())).getRoot());

//        SerialPortDebug.onStart(SerialInode.from("ttyS10"));
//        SerialPortDebug.onStart(SerialInode.from("ttyS3"));

        insert("\n");
        invoke();
    }

    @SuppressLint("NewApi")
    public void invoke() {
        ArrayList<SerialInode> ttyList = SerialInode.ttys();

        // 并行计算
        Loople.Task.allOf(ttyList, inode -> {
                    SerialPipeline pipeline = SerialPipeline.start(inode);
                    if (pipeline != null && pipeline.valid()) {
                        Semver semver = new Semver().parse(M2spLite.versionOf(pipeline));
                        if (semver.valid()) {
                            pipeline.onConnected();

                            Loople.Task.slice(() -> {
                                Potency poty = Potency.start();
                                long temp = -1;

                                if (pipeline.valid()) {
                                    try {
                                        UnitMeta meta = pipeline.get(TEMPERATURE);
                                        if (meta != null) {
                                            temp = M2spLite.valueOf(meta);

                                            Log.i(TAG, "TEMPERATURE: %d, TIME: %dms", temp, poty.record());
                                            insert(".%s", mRunState.get() ? "\n" : "");
                                            mRunState.set(false);
                                        } else {
                                            Log.e(TAG, "[ERROR]: UnitMeta()");
                                            insert("[ERROR]: UnitMeta()\n");
                                            mRunState.set(true);
                                        }
                                    } catch (Exception e) {
                                        Log.w(TAG, e.getMessage());
                                        insert("%s\n", e.getMessage());
                                        mRunState.set(true);
                                    }
                                } else {
                                    Log.e(TAG, "[ERROR]: valid()");
                                    insert("[ERROR]: valid()\n");
                                    mRunState.set(true);
                                }
                            }, 1000, 500, MILLISECONDS);
                        }
                    }
                }
        );
    }

    private void insert(String format, Object... args) {
        runOnUiThread(() -> binding.logcat.setText(new StringBuilder(binding.logcat.getText()).insert(0, Chars.format(format, args)).toString()));
    }
}